package tp.pr4.instructions;

import java.util.StringTokenizer;

import tp.pr4.NavigationModule;
import tp.pr4.RobotEngine;
import tp.pr4.instructions.exceptions.*;
import tp.pr4.items.ItemContainer;
import tp.pr4.items.Item;

/**
 * The execution of this instruction shows the information of the inventory 
 * of the robot or the complete description about the item with identifier 
 * id contained in the inventory This Instruction works if the player writes 
 * SCAN or ESCANEAR (id is not mandatory)
 * @author Alvaro Saez Hernando
 * @author Noel Clemente Montero 
 */
public class ScanInstruction implements Instruction {

	private static final String LINE_SEPARATOR = System.lineSeparator();
	private String id;
	private ItemContainer robotContainer;
	
	/**
	 * Default constructor.
	 */
	public ScanInstruction() {
		this.robotContainer = new ItemContainer();
		this.id = "";
	}
	
	/**
	 * Creates a ScanInstruction using a ID 
	 * @param id
	 */
	public ScanInstruction(String id) {
		this.id = id;
	}

	/**
	 * Parses the String returning a ScanInstruction instance or throwing a 
	 * WrongInstructionFormatException()
	 * @param cad - text String to parse
	 * @return Instruction Reference to an instance of ScanInstruction
	 * @throws WrongInstructionFormatException - When the String is not SCAN | ESCANEAR [id]
	 */
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		
		StringTokenizer st = new StringTokenizer(cad, " ");
		String words = st.nextToken().toUpperCase();
		
		if ((words.equals("SCAN")) || (words.equals("ESCANEAR"))) {
			if (st.hasMoreTokens()) {
				String id = st.nextToken();
				if (!st.hasMoreTokens())
					return new ScanInstruction(id);
				else
					throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
			} else
				return new ScanInstruction();
		} else
			throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
	}

	/**
	 * Returns a description of the Instruction syntax. The string does not end 
	 * with the line separator. It is up to the caller adding it before printing.
	 * @return the Instruction syntax of the instruction SCAN | ESCANEAR [id]
	 */
	public String getHelp() {
		return "SCAN|ESCANEAR <id>" + LINE_SEPARATOR;
	}

	/**
	 * Set the execution context. The method receives the entire engine (engine,
	 * navigation and the robot container) even though the actual implementation 
	 * of execute() may not require it.
	 * @param engine - The robot engine
	 * @param navigation - The information about the game, i.e., the places, 
	 * current direction and current heading to navigate
	 * @param robotContainer - The inventory of the robot 
	 */
	public void configureContext(RobotEngine engine, NavigationModule navigation, ItemContainer robotContainer) {
		this.robotContainer = robotContainer;
	}

	/**
	 * Prints the description of a concrete item or the complete inventory of the robot
	 * @throws InstructionExecutionException - When the robot does not contain the item to be scanned
	 */
	public void execute() throws InstructionExecutionException {
		
		if (id.equalsIgnoreCase("")) {
			if(robotContainer.numberOfItems()==0){
				throw new InstructionExecutionException("WALL·E says: My inventory is empty");
			}
			else System.out.println(robotContainer.viewItems());
		} else {
			Item item = robotContainer.getItem(id);
			if (item != null)
				System.out.println("WALL·E says: " + item.toString() + LINE_SEPARATOR);
			else
				throw new InstructionExecutionException("WALL·E says: I have not such object" + LINE_SEPARATOR);
		}
		
	}

}
